home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / morph.c < prev    next >
C/C++ Source or Header  |  1996-04-11  |  27KB  |  896 lines

  1. #include "morph.hpp"
  2.  
  3. long trans(long x1, long x2, long frame)
  4. {
  5.   return (((x2-x1)<<5)*frame+(x1<<8))>>8;  
  6. }
  7.  
  8.  
  9. void jmorph::show_step_frame(image *screen, int x, int y, int frame_on,
  10.                    color_filter *fli, palette *pal)
  11. {
  12.   short x1,y1,x2,y2;
  13.   unsigned char r1,g1,b1,r2,g2,b2;
  14.   screen->get_clip(x1,y1,x2,y2);
  15.   
  16.   int i;
  17.   long xx,yy;
  18.   
  19.   if (small)
  20.   {
  21.     morph_point8 *m8=(morph_point8 *)p;
  22.     for (i=0;i<total;i++,m8++)
  23.     {
  24.       xx=x+trans(m8->x1,m8->x2,frame_on);
  25.       yy=y+trans(m8->y1,m8->y2,frame_on);
  26.       
  27.       if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
  28.       {    
  29.     pal->get(m8->start_color,r1,g1,b1);
  30.     pal->get(m8->end_color,r2,g2,b2);
  31.   
  32.     long r=trans(r1,r2,frame_on)>>3,
  33.              g=trans(g1,g2,frame_on)>>3,
  34.          b=trans(b1,b2,frame_on)>>3;
  35.     
  36.         *(screen->scan_line(yy)+xx)=fli->lookup_color(r,g,b);
  37.       }            
  38.     }
  39.   }    
  40. }
  41.  
  42.  
  43. void patched_morph::show_frame(image *screen, int x, int y, 
  44.                    int frame_on, color_filter *fli, palette *pal)
  45. {
  46.   jmorph::show_step_frame(screen,x,y,frame_on,fli,pal);
  47.   int tot=pats[frame_on].patches,xx,yy;
  48.   unsigned char *p=pats[frame_on].patch_data;
  49.   short cx1,cy1,cx2,cy2;
  50.   screen->get_clip(cx1,cy1,cx2,cy2);    
  51.   while (tot--)
  52.   {
  53.     xx=*(p++)+x;
  54.     if (xx<cx1 || xx>cx2)
  55.       p+=2;
  56.     else
  57.     {
  58.       yy=*(p++)+y;
  59.       if (yy<cy1 || yy>cy2)
  60.         p++;
  61.       else
  62.     *(screen->scan_line(yy)+xx)=*(p++);
  63.     }
  64.   }      
  65. }
  66.  
  67. void patched_morph::show_8(image *screen, int x, int y, int frame_on, color_filter *fli, palette *pal)
  68. {
  69.   jmorph::show_8(screen,x,y,frame_on,fli,pal);
  70.   int tot=pats[frame_on].patches,xx,yy; 
  71.   unsigned char *p=pats[frame_on].patch_data;
  72.   short cx1,cy1,cx2,cy2;
  73.   screen->get_clip(cx1,cy1,cx2,cy2);    
  74.   while (tot--)
  75.   {
  76.     xx=*(p++)+x;
  77.     if (xx<cx1 || xx>cx2)
  78.       p+=2;
  79.     else
  80.     {
  81.       yy=*(p++)+y;
  82.       if (yy<cy1 || yy>cy2)
  83.         p++;
  84.       else
  85.     *(screen->scan_line(yy)+xx)=*(p++);
  86.     }
  87.   }      
  88. }
  89.  
  90.  
  91.  
  92.  
  93. patched_morph::patched_morph(image *i1, image *hint1, image *i2, image *hint2, int aneal_steps,
  94.             color_filter *fli, palette *pal, int frames) : jmorph(i1,hint1,i2,hint2,aneal_steps)
  95. {
  96.   int i,j,w,h,x,y,tot,r,g,b,mark_color,dist;
  97.   unsigned char *cur_patch,*sl,or,og,ob;
  98.   
  99.   frames=9;
  100.   
  101.   patches=frames;  
  102.   pats=(morph_patch *)jmalloc(sizeof(morph_patch)*patches,"morph::patch array");
  103.   w=max(bound_x2(0),bound_x2(1));
  104.   h=max(bound_y2(0),bound_y2(1));    
  105.   image *im=new image(w,h);
  106.  
  107.  
  108.   for (i=0;i<patches;i++)
  109.   {
  110.     pats[i].patch_data=NULL;
  111.     pats[i].patches=0;    
  112.     if (i!=0 && i!=patches-1)
  113.     {      
  114.       im->clear();
  115.       jmorph::show_step_frame(im,0,0,i,fli,pal);
  116.       for (j=0;j<4;j++)
  117.       {      
  118.     for (y=0;y<h;y++)
  119.           for (sl=im->scan_line(y),x=0;x<w;x++,sl++)
  120.       {    
  121.         mark_color=-1;
  122.         
  123.         tot=r=g=b=0;            
  124.         if (x!=0 && *(sl-1)) 
  125.         { tot++; 
  126.           r+=pal->red(*(sl-1)); 
  127.           g+=pal->green(*(sl-1)); 
  128.           b+=pal->blue(*(sl-1));           
  129.         }      
  130.         if (x!=w-1 && *(sl+1)) 
  131.         { tot++; 
  132.           r+=pal->red(*(sl+1)); 
  133.           g+=pal->green(*(sl+1)); 
  134.           b+=pal->blue(*(sl+1));    
  135.         }      
  136.         if (y!=0 && im->pixel(x,y-1)) 
  137.         { tot++; 
  138.           r+=pal->red(im->pixel(x,y-1)); 
  139.           g+=pal->green(im->pixel(x,y-1)); 
  140.           b+=pal->blue(im->pixel(x,y-1));
  141.         }
  142.         if (y!=h-1 && im->pixel(x,y+1)) 
  143.         { tot++; 
  144.           r+=pal->red(im->pixel(x,y+1)); 
  145.           g+=pal->green(im->pixel(x,y+1)); 
  146.           b+=pal->blue(im->pixel(x,y+1));
  147.         }
  148.  
  149.         if (*sl && tot==0)  // kill any seperate pixels        
  150.           mark_color=0;
  151.         else if (*sl)
  152.         {
  153.           pal->get(*sl,or,og,ob);       // see if we need to blur this on in
  154.           r/=tot;
  155.           g/=tot;
  156.           b/=tot;
  157.           
  158.           dist=((int)or-r)*((int)or-r)+((int)og-g)*((int)og-g)+((int)ob-b)*((int)ob-b);
  159.           if (i>0 && i<patches-1 && dist>3000)
  160.           {
  161. //        printf("adding blur at %d %d to frame %d, dist=%d\n",x,y,i,dist);
  162.         mark_color=fli->lookup_color(r>>3,g>>3,b>>3);        
  163.           }
  164.         }
  165.         else if (*sl==0 && tot>=3)        
  166.           mark_color=fli->lookup_color((r/tot)>>3,(g/tot)>>3,(b/tot)>>3);        
  167.         if (mark_color>=0)
  168.         {          
  169.           pats[i].patches++;
  170.           pats[i].patch_data=(unsigned char *)realloc(pats[i].patch_data,3*pats[i].patches);
  171.           cur_patch=pats[i].patch_data+  (pats[i].patches-1)*3;        
  172.           *(cur_patch++)=x;
  173.           *(cur_patch++)=y;
  174.           *sl=mark_color;          
  175.           *(cur_patch++)=*sl;          
  176.         }      
  177.       }
  178.       }      
  179.     }
  180.   }  
  181.   delete im;
  182.   
  183. }
  184.  
  185.  
  186. void jmorph::show_8(image *screen, int x, int y, int frame_on, color_filter *fli, palette *pal)
  187. {
  188.   int pixelx,pixely,i;
  189.   short cx1,cy1,cx2,cy2;
  190.   unsigned char r,g,b;
  191.   unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr();
  192.   screen->get_clip(cx1,cy1,cx2,cy2);
  193.  
  194.   if (small)
  195.   {
  196.     morph_point8 *p_on=(morph_point8 *)p;
  197.     for (i=0;i<total;i++,p_on++)
  198.     {
  199.       pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/8+p_on->x1+x;
  200.       pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/8+p_on->y1+y;
  201.       if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
  202.       {
  203.         scolor=addr+((int)p_on->start_color)*3;
  204.         ecolor=addr+((int)p_on->end_color)*3;
  205.         r=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
  206.         g=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
  207.         b=((int)(*ecolor)-(int)(*scolor))*frame_on/8+*scolor;
  208.         *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
  209.       }
  210.     }
  211.   }
  212.   else
  213.   {
  214.     morph_point16 *p_on=(morph_point16 *)p;
  215.     for (i=0;i<total;i++,p_on++)
  216.     {
  217.       pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/8+p_on->x1+x;
  218.       pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/8+p_on->y1+y;
  219.       if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
  220.       {
  221.         scolor=addr+((int)p_on->start_color)*3;
  222.         ecolor=addr+((int)p_on->end_color)*3;
  223.         r=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
  224.         g=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
  225.         b=((int)(*ecolor)-(int)(*scolor))*frame_on/8+*scolor;
  226.         *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
  227.       }
  228.     }
  229.   }
  230. }  
  231.  
  232.  
  233. void jmorph::add_filler(int frames)
  234. {
  235.   int w=max(bound_x2(0),bound_x2(1)),h=max(bound_y2(0),bound_y2(1)),
  236.       i,pixelx,pixely,k,l,frame_on;  
  237.   morph_point8 **middle_map,*other;
  238.   unsigned char *end_map;
  239.   CONDITION(small,"add filler not defined for 16bit morphs\n");
  240.   
  241.   if (frames<3) return ;
  242.   
  243.  
  244.   middle_map=(morph_point8 **)jmalloc(w*h*sizeof(morph_point8 *),
  245.                       "morph::middle_map");  // create an image of pointers
  246.   end_map=(unsigned char *)jmalloc(w*h,
  247.                   "morph::end_map");      // maps all the ending pixels
  248.  
  249.   for (frame_on=2;frame_on<frames-1;frame_on++)
  250.   {    
  251.     memset(middle_map,0,w*h*sizeof(morph_point8 *));            // initialize them middle pointers NULL
  252.     memset(end_map,0,w*h);                                      // clear all end pixels
  253.   
  254.     morph_point8 *p_on=(morph_point8 *)p;    // p is the array of morph points
  255.     for (i=0;i<total;i++,p_on++)            
  256.     {    
  257.       pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long) frame_on  /(long) frames  +p_on->x1;
  258.       pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long) frame_on  /(long) frames  +p_on->y1;
  259.  
  260.       middle_map[pixelx+pixely*w]=p_on;      // map this poisiton back to the morph point
  261.       end_map[p_on->x2+p_on->y2*w]=p_on->end_color;        // note an ending map here
  262.     }
  263.  
  264.   
  265.     int skipped=0;
  266.     
  267.     for (pixely=0;pixely<h;pixely++)
  268.     {
  269.       for (pixelx=0;pixelx<w;pixelx++)
  270.       { 
  271.     if (middle_map[pixelx+pixely*w]==NULL)  // we are checking for 'duds'  (misplaced black pixels)
  272.     {    
  273.       int tot;    
  274.       if (pixelx>0) if (middle_map[pixelx-1+pixely*w]) tot=1; else tot=0;      
  275.       if (pixelx<w-1) if (middle_map[pixelx+1+pixely*w]) tot++;    
  276.       if (pixely>0) if (middle_map[pixelx+(pixely-1)*w]) tot++;    
  277.       if (pixely<h-1) if (middle_map[pixelx+(pixely+1)*w]) tot++;    
  278.  
  279.       if (tot>=3)                   // it is surronded by 3 non black squares, this is a dud    
  280.       {
  281.         int distance,shortest_distance,shortest_end_x,shortest_end_y;      
  282.         morph_point8 *shortest=NULL;
  283.         
  284.         for (k=0;k<w;k++)
  285.              for (l=0;l<h;l++)
  286.           {          
  287.                 other=middle_map[k+(l)*w];
  288.         if (other)
  289.         {
  290.           int end_x=frames*(pixelx-other->x1)/frame_on+other->x1,
  291.               end_y=frames*(pixely-other->y1)/frame_on+other->y1;          
  292.           if (end_x>=0 && end_y>=0 && end_x<w && end_y<h && end_map[end_x+end_y*w])
  293.           { 
  294.                     distance=(other->x1-end_x)*(other->x1-end_x)+
  295.                      (other->y1-end_y)*(other->y1-end_y);
  296.             if (!shortest || shortest_distance>distance)
  297.             {
  298.               shortest_distance=distance;
  299.               shortest=other;
  300.               shortest_end_x=end_x;
  301.               shortest_end_y=end_y;              
  302.             }
  303.           }
  304.         }
  305.           }        
  306.         if (shortest)
  307.         {
  308.           total++;
  309.           p=(void *)realloc(p,sizeof(morph_point8)*total);          
  310.           morph_point8 *mod=((morph_point8 *)p)+total-1;
  311.           mod->x1=shortest->x1;
  312.           mod->y1=shortest->y1;
  313.           mod->start_color=shortest->start_color;          
  314.  
  315.           mod->x2=shortest_end_x;
  316.           mod->y2=shortest_end_y;          
  317.           mod->end_color=end_map[shortest_end_x+shortest_end_y*w];          
  318.         }        
  319.         else
  320.         {          
  321.             skipped++;
  322.           printf("skiped so far : %d (frame %d)\n",skipped,frame_on);
  323.         }
  324.         
  325.  
  326.       }    
  327.     }
  328.       }
  329.     }  
  330.   }
  331.   
  332.   jfree(middle_map);
  333.   jfree(end_map);
  334.   
  335. }
  336.  
  337.  
  338.  
  339. jmorph::jmorph(spec_entry *e, bFILE *fp)
  340. {
  341.   int i;
  342.   fp->seek(e->offset,0);
  343.   fp->read(&total,4);  
  344.   total=long_to_local(total);
  345.   if (e->type==SPEC_MORPH_POINTS_8 || e->type==SPEC_PATCHED_MORPH)
  346.   {
  347.     p=(void *)jmalloc(sizeof(morph_point8)*total,"morph8::point array");
  348.     fp->read(p,sizeof(morph_point8)*total);
  349.     small=1;
  350.   }
  351.   else
  352.   {
  353.     p=(void *)jmalloc(sizeof(morph_point16)*total,"morph16::point array");
  354.  
  355.     for (i=0;i<total;i++)
  356.     { 
  357.       ((morph_point16 *)p+i)->x1=fp->read_short();
  358.       ((morph_point16 *)p+i)->y1=fp->read_short();
  359.       ((morph_point16 *)p+i)->x2=fp->read_short();
  360.       ((morph_point16 *)p+i)->y2=fp->read_short();
  361.       fp->read( &((morph_point16 *)p+i)->start_color,1);
  362.       fp->read( &((morph_point16 *)p+i)->end_color,1);
  363.     }
  364.  
  365.     small=0;
  366.   }
  367.   w[0]=fp->read_short();
  368.   h[0]=fp->read_short();  
  369.   w[1]=fp->read_short();
  370.   h[1]=fp->read_short();
  371. }
  372.  
  373. void jmorph::show_frame(image *screen, int x, int y, 
  374.                       int frames, int frame_on, color_filter *fli, palette *pal)
  375. {
  376.   int pixelx,pixely,i;
  377.   short cx1,cy1,cx2,cy2;
  378.   unsigned char r,g,b;
  379.   unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr();
  380.   screen->get_clip(cx1,cy1,cx2,cy2);
  381.  
  382.   if (small)
  383.   {
  384.     morph_point8 *p_on=(morph_point8 *)p;
  385.     for (i=0;i<total;i++,p_on++)
  386.     {
  387.       pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
  388.       pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
  389.       if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
  390.       {
  391.         scolor=addr+((int)p_on->start_color)*3;
  392.         ecolor=addr+((int)p_on->end_color)*3;
  393.         r=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
  394.         g=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
  395.         b=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
  396.         *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
  397.       }
  398.     }
  399.   }
  400.   else
  401.   {
  402.     morph_point16 *p_on=(morph_point16 *)p;
  403.     for (i=0;i<total;i++,p_on++)
  404.     {
  405.       pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
  406.       pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
  407.       if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
  408.       {
  409.         scolor=addr+((int)p_on->start_color)*3;
  410.         ecolor=addr+((int)p_on->end_color)*3;
  411.         r=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
  412.         g=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
  413.         b=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
  414.         *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
  415.       }
  416.     }
  417.   }
  418. }  
  419.  
  420. void jmorph::show_24frame(unsigned char *screen, int width, int height,
  421.                   int x, int y, int frames, int frame_on, palette *pal)
  422. {
  423.     int pixelx,pixely,i;
  424.   unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr(),*pix;
  425.  
  426.   if (small)
  427.   {
  428.     morph_point8 *p_on=(morph_point8 *)p;
  429.     for (i=0;i<total;i++,p_on++)
  430.     {
  431.       pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
  432.       pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
  433.  
  434.       if (pixelx>=0 && pixely>=0 && pixelx<width && pixely<height)
  435.       {    
  436.         scolor=addr+((int)p_on->start_color)*3;
  437.         ecolor=addr+((int)p_on->end_color)*3;
  438.         pix=screen+pixelx*3+pixely*3*width;               
  439.         *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;    
  440.         *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;    
  441.         *pix=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
  442.       }
  443.     }
  444.   }
  445.   else
  446.   {
  447.     morph_point16 *p_on=(morph_point16 *)p;
  448.     for (i=0;i<total;i++,p_on++)
  449.     {
  450.       pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
  451.       pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
  452.  
  453.       if (pixelx>=0 && pixely>=0 && pixelx<width && pixely<height)
  454.       {    
  455.         scolor=addr+((int)p_on->start_color)*3;
  456.         ecolor=addr+((int)p_on->end_color)*3;
  457.         pix=screen+pixelx*3+pixely*3*width;               
  458.         *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;    
  459.         *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;    
  460.         *pix=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
  461.       }
  462.     }
  463.   }
  464. }
  465.  
  466.  
  467. jmorph::jmorph(image *i1, image *hint1, image *i2, image *hint2, 
  468.                           int aneal_steps)
  469. {
  470.   w[0]=i1->width();
  471.   h[0]=i1->height();  
  472.   w[1]=i2->width();
  473.   h[1]=i2->height();  
  474.  
  475.   struct { int start,end; } crange[256];
  476.   int hint_hist1[256],hint_hist2[256],x,y,total_hints=0,randp,cur_pix,
  477.       last=0,first=0,i,j,k,findx1,findy1,findx2,findy2,total1,total2,points;
  478.   unsigned char *sl,color;
  479.   void *plist;
  480.  
  481.  
  482.   CONDITION(i1->width()==hint1->width() && i1->height()==hint1->height() && 
  483.             i2->width()==hint2->width() && i2->height()==hint2->height(),
  484.             "Image sizes do not correspond with hint sizes");
  485.   if (i1->width()>255 || i2->width()>255 || i1->height()>255 || i2->height()>255) 
  486.     small=0;
  487.   else small=1;
  488.  
  489.   memset(hint_hist1,0,sizeof(hint_hist1));
  490.   memset(hint_hist2,0,sizeof(hint_hist2));
  491.   total=0;
  492.  
  493.   // first found out how many hints we have to follow
  494.   for (y=0;y<hint1->height();y++)
  495.   { sl=hint1->scan_line(y);
  496.     for (x=hint1->width();x;x--,sl++)
  497.       if (*sl) hint_hist1[*sl]++;
  498.   }
  499.   for (y=0;y<hint2->height();y++)
  500.   { sl=hint2->scan_line(y);
  501.     for (x=hint2->width();x;x--,sl++)
  502.       if (*sl) hint_hist2[*sl]++;
  503.   }
  504.  
  505.   // check the user and see if the mask match up
  506.   for (x=0;x<256;x++) 
  507.   {
  508.     if ((hint_hist1[x]!=0 && hint_hist2[x]==0) ||
  509.         (hint_hist1[x]==0 && hint_hist2[x]!=0))
  510.     { printf("Color %d used for hinting is prent in one hint mask, but not the other\n",x);
  511.       exit(1);
  512.     } else if (hint_hist1[x])
  513.     { 
  514.       if (!first) first=x;
  515.       total_hints++;
  516.       if (hint_hist1[x]>hint_hist2[x])
  517.         y=hint_hist1[x];
  518.       else
  519.         y=hint_hist2[x];
  520.       total+=y;
  521.       crange[x].start=last;
  522.       crange[x].end=last+y-1;
  523.       last+=y;
  524.     }
  525.   }
  526.   if (small)
  527.     plist=(void *)jmalloc(sizeof(morph_point8)*total,"morph8::point array");
  528.   else
  529.     plist=(void *)jmalloc(sizeof(morph_point16)*total,"morph16::point array");
  530.   CHECK(plist);
  531.   for (i=0,color=0;i<total_hints;i++)
  532.   {
  533.     color++; while (!hint_hist1[color]) color++;
  534.     findx1=findx2=-1; findy1=findy2=0;
  535.     total1=hint_hist1[color];
  536.     total2=hint_hist2[color];
  537.     if (total1>total2) points=total1; else points=total2;
  538.     for (j=0;j<points;j++)
  539.     {
  540.       if (total1)  // are there any more pixels left in this image?
  541.       { total1--;
  542.         do {
  543.           findx1++; 
  544.           if (findx1>=hint1->width()) { findx1=0; findy1++; } 
  545.         } while (hint1->pixel(findx1,findy1)!=color);
  546.       }
  547.       else
  548.       {
  549.         randp=rand()%j+crange[color].start;
  550.         if (small)
  551.         { findx1=((morph_point8 *)plist)[randp].x1; 
  552.           findy1=((morph_point8 *)plist)[randp].y1;
  553.         } else
  554.         { findx1=((morph_point16 *)plist)[randp].x1; 
  555.           findy1=((morph_point16 *)plist)[randp].y1;
  556.         }
  557.       }
  558.       if (total2)  // are there any more pixels left in this image?
  559.       { 
  560.         total2--;
  561.         do {
  562.           findx2++; 
  563.           if (findx2>=hint2->width()) { findx2=0; findy2++; } 
  564.         } while (hint2->pixel(findx2,findy2)!=color);
  565.       }
  566.       else
  567.       {
  568.         randp=rand()%j+crange[color].start;
  569.         if (small)
  570.         { findx2=((morph_point8 *)plist)[randp].x2; 
  571.           findy2=((morph_point8 *)plist)[randp].y2;
  572.         } else
  573.         { findx2=((morph_point16 *)plist)[randp].x2; 
  574.           findy2=((morph_point16 *)plist)[randp].y2;
  575.         }
  576.       }
  577.       cur_pix=j+crange[color].start;
  578.       CHECK(cur_pix<total);
  579.  
  580.       if (small)
  581.       {
  582.         ((morph_point8 *)plist)[cur_pix].x1=findx1;  
  583.         ((morph_point8 *)plist)[cur_pix].x2=findx2;  
  584.         ((morph_point8 *)plist)[cur_pix].y1=findy1;  
  585.         ((morph_point8 *)plist)[cur_pix].y2=findy2;  
  586.         ((morph_point8 *)plist)[cur_pix].start_color=i1->pixel(findx1,findy1);
  587.         ((morph_point8 *)plist)[cur_pix].end_color=i2->pixel(findx2,findy2);
  588.       }
  589.       else
  590.       {
  591.         ((morph_point16 *)plist)[cur_pix].x1=findx1;  
  592.         ((morph_point16 *)plist)[cur_pix].x2=findx2;  
  593.         ((morph_point16 *)plist)[cur_pix].y1=findy1;  
  594.         ((morph_point16 *)plist)[cur_pix].y2=findy2;  
  595.         ((morph_point16 *)plist)[cur_pix].start_color=i1->pixel(findx1,findy1);
  596.         ((morph_point16 *)plist)[cur_pix].end_color=i2->pixel(findx2,findy2);
  597.       }
  598.     }
  599.   }
  600.   int swap_point,distance,new_distance,hint_color,first_point,range,start;
  601.  
  602.   int sx2,sy2,sec;
  603.   for (i=0;i<aneal_steps;i++)
  604.   {
  605.     for (j=0,first_point=0;j<total_hints;j++)
  606.     {
  607.       if (small)
  608.         hint_color=hint1->pixel(((morph_point8 *)plist)[first_point].x1,((morph_point8 *)plist)[first_point].y1);
  609.       else
  610.         hint_color=hint1->pixel(((morph_point16 *)plist)[first_point].x1,((morph_point16 *)plist)[first_point].y1);
  611.       start=crange[hint_color].start;
  612.       range=crange[hint_color].end-start+1;
  613.       for(k=crange[hint_color].start;k<=crange[hint_color].end;k++) 
  614.       {
  615.         swap_point=rand()%range+start;
  616.         if (small)
  617.         {
  618.           morph_point8 *pk,*ps;
  619.           pk=(morph_point8 *)plist+k;
  620.           ps=(morph_point8 *)plist+swap_point;
  621.  
  622.           distance=(pk->x2-pk->x1)*(pk->x2-pk->x1)+(pk->y2-pk->y1)*(pk->y2-pk->y1)+
  623.                    (ps->x2-ps->x1)*(ps->x2-ps->x1)+(ps->y2-ps->y1)*(ps->y2-ps->y1);
  624.           new_distance=(ps->x2-pk->x1)*(ps->x2-pk->x1)+(ps->y2-pk->y1)*(ps->y2-pk->y1)+
  625.                        (pk->x2-ps->x1)*(pk->x2-ps->x1)+(pk->y2-ps->y1)*(pk->y2-ps->y1);
  626.           if (new_distance<distance)
  627.           { 
  628.             sx2=pk->x2;         sy2=pk->y2;
  629.             sec=pk->end_color;
  630.             pk->x2=ps->x2;      pk->y2=ps->y2;
  631.             pk->end_color=ps->end_color;
  632.             ps->x2=sx2;         ps->y2=sy2;
  633.             ps->end_color=sec;
  634.           }
  635.         } else
  636.         {
  637.           morph_point16 *pk,*ps;
  638.           pk=(morph_point16 *)plist+k;
  639.           ps=(morph_point16 *)plist+swap_point;
  640.  
  641.           distance=(pk->x2-pk->x1)*(pk->x2-pk->x1)+(pk->y2-pk->y1)*(pk->y2-pk->y1)+
  642.                    (ps->x2-ps->x1)*(ps->x2-ps->x1)+(ps->y2-ps->y1)*(ps->y2-ps->y1);
  643.           new_distance=(ps->x2-pk->x1)*(ps->x2-pk->x1)+(ps->y2-pk->y1)*(ps->y2-pk->y1)+
  644.                        (pk->x2-ps->x1)*(pk->x2-ps->x1)+(pk->y2-ps->y1)*(pk->y2-ps->y1);
  645.           if (new_distance<distance)
  646.           { 
  647.             sx2=pk->x2;         sy2=pk->y2;
  648.             sec=pk->end_color;
  649.             pk->x2=ps->x2;      pk->y2=ps->y2;
  650.             pk->end_color=ps->end_color;
  651.             ps->x2=sx2;         ps->y2=sy2;
  652.             ps->end_color=sec;
  653.           }
  654.         }
  655.       }
  656.       first_point=crange[hint_color].end+1;
  657.     }
  658.   }
  659.   p=plist;
  660.  
  661. int morph_width;
  662.  
  663. int morph8_compare(const void *p1, const void *p2)
  664. {
  665.   int pos1=((morph_point8 *)p1)->x1+((morph_point8 *)p1)->y1*morph_width;  
  666.   int pos2=((morph_point8 *)p2)->x1+((morph_point8 *)p2)->y1*morph_width;  
  667.   if (pos1<pos2) return -1;
  668.   else if (pos1==pos2) return 0;
  669.   else return 1;
  670.   
  671. }
  672.  
  673.  
  674. int jmorph::write(bFILE *fp)
  675. {
  676.   int i;
  677.  
  678.   
  679.   fp->write_long(total);  
  680.   if (small)
  681.   {
  682.  
  683.     // if the points are put in order then they can be compressed easier
  684.     morph_width=max(bound_x2(0),bound_x2(1));      // global used by qsort compare routine
  685.     qsort(p,total,sizeof(morph_point8),morph8_compare);  
  686.     
  687.     fp->write(p,sizeof(morph_point8)*total); 
  688.   }  
  689.   else
  690.   {
  691.     for (i=0;i<total;i++)
  692.     { fp->write_short(((morph_point16 *)p+i)->x1);
  693.       fp->write_short(((morph_point16 *)p+i)->y1);
  694.       fp->write_short(((morph_point16 *)p+i)->x2);
  695.       fp->write_short(((morph_point16 *)p+i)->y2);
  696.       fp->write( &((morph_point16 *)p+i)->start_color,1);
  697.       fp->write( &((morph_point16 *)p+i)->end_color,1);
  698.     }
  699.   }
  700.   fp->write_short(w[0]);
  701.   fp->write_short(h[0]);
  702.   fp->write_short(w[1]);
  703.   fp->write_short(h[1]);
  704.   return 1;
  705. }
  706.  
  707.  
  708.  
  709.  
  710. step_morph::step_morph(patched_morph *mor, palette *pal, int frame_direction, int face_direction)
  711. {
  712.   int i;
  713.   pm=mor;
  714.   
  715.   total=mor->total_points();      
  716.   points=(step_struct *)jmalloc(sizeof(step_struct)*total,"step_morph::points");  
  717.   
  718.   dir=frame_direction;
  719.   face_dir=face_direction;
  720.   
  721.   if (dir>0)
  722.     frame_on=0;
  723.   else
  724.     frame_on=mor->patches-1;
  725.   
  726.   if (mor->small_morph())
  727.   {    
  728.       int x1,y1,x2,y2;
  729.  
  730.     
  731.       if (frame_direction>0)
  732.       {      
  733.     morph_point8 *m8=mor->small_points();      
  734.     
  735.     for (i=0;i<total;i++,m8++)
  736.     {         
  737.       x1=(int)m8->x1;
  738.       x2=(int)m8->x2;
  739.  
  740.       y1=(int)m8->y1;
  741.       y2=(int)m8->y2;
  742.  
  743.       points[i].x=x1<<8;
  744.       points[i].y=y1<<8;       
  745.       points[i].dx=(x2-x1)<<5;
  746.       points[i].dy=(y2-y1)<<5;        
  747.          
  748.       unsigned char r1,g1,b1,r2,g2,b2;
  749.       pal->get(m8->start_color,r1,g1,b1);
  750.       pal->get(m8->end_color,r2,g2,b2);
  751.       points[i].r=r1<<8;
  752.       points[i].g=g1<<8;
  753.       points[i].b=b1<<8;
  754.  
  755.       points[i].dr=(long)((int)r2-(int)r1)<<5;
  756.       points[i].dg=(long)((int)g2-(int)g1)<<5;
  757.       points[i].db=(long)((int)b2-(int)b1)<<5;            
  758.     }
  759.       }    
  760.       else
  761.       {      
  762.     morph_point8 *m8=mor->small_points();      
  763.     for (i=0;i<total;i++,m8++)
  764.     {         
  765.       x1=(int)m8->x1;
  766.       x2=(int)m8->x2;
  767.  
  768.       y1=(int)m8->y1;
  769.       y2=(int)m8->y2;
  770.  
  771.       points[i].x=x2<<8;
  772.       points[i].y=y2<<8;       
  773.       points[i].dx=(x1-x2)<<5;
  774.       points[i].dy=(y1-y2)<<5;        
  775.  
  776.       unsigned char r1,g1,b1,r2,g2,b2;
  777.       pal->get(m8->start_color,r2,g2,b2);
  778.       pal->get(m8->end_color,r1,g1,b1);
  779.       points[i].r=r1<<8;
  780.       points[i].g=g1<<8;
  781.       points[i].b=b1<<8;
  782.  
  783.       points[i].dr=(long)((int)r2-(int)r1)<<5;
  784.       points[i].dg=(long)((int)g2-(int)g1)<<5;
  785.       points[i].db=(long)((int)b2-(int)b1)<<5;            
  786.     }
  787.       }    
  788.   }  
  789.  
  790.  
  791. }
  792.  
  793. void step_morph::show_frame(image *screen, int x, int y,  color_filter *fli)
  794. {
  795.   short x1,y1,x2,y2;
  796.   screen->get_clip(x1,y1,x2,y2);
  797.  
  798.   int i,px,py,ww=max(pm->bound_x2(0),pm->bound_x2(1))-1;
  799.   step_struct *ss;
  800.  
  801.   morph_patch *pat=pm->pats+frame_on;  
  802.   int j,tp=pat->patches;
  803.   unsigned char *sl=pat->patch_data;    
  804.  
  805.   if (face_dir>0)
  806.   {    
  807.     for (i=0,ss=points;i<total;i++,ss++)
  808.     {
  809.       px=x+(ss->x>>(16-8));
  810.       py=y+(ss->y>>(16-8));
  811.       if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
  812.         *(screen->scan_line(py)+px)=fli->lookup_color(ss->r>>(19-8),ss->g>>(19-8),ss->b>>(19-8));
  813.  
  814.       ss->x+=ss->dx;
  815.       ss->y+=ss->dy;
  816.       ss->r+=ss->dr;
  817.       ss->g+=ss->dg;
  818.       ss->b+=ss->db;        
  819.     }  
  820.  
  821.     for (j=0;j<tp;j++,sl++)
  822.     {
  823.       px=x+*(sl++);
  824.       py=y+*(sl++);
  825.       if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
  826.         *(screen->scan_line(py)+px)=*sl;
  827.     }             
  828.   } else
  829.   {
  830.     for (i=0,ss=points;i<total;i++,ss++)
  831.     {
  832.       px=x+ww-(ss->x>>(16-8));
  833.       py=y+(ss->y>>(16-8));
  834.       if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
  835.         *(screen->scan_line(py)+px)=fli->lookup_color(ss->r>>(19-8),ss->g>>(19-8),ss->b>>(19-8));
  836.  
  837.       ss->x+=ss->dx;
  838.       ss->y+=ss->dy;
  839.       ss->r+=ss->dr;
  840.       ss->g+=ss->dg;
  841.       ss->b+=ss->db;        
  842.     }  
  843.  
  844.     for (j=0;j<tp;j++,sl++)
  845.     {
  846.       px=x+(ww-(int)(*(sl++)));
  847.       py=y+*(sl++);
  848.       if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
  849.         *(screen->scan_line(py)+px)=*sl;
  850.     }          
  851.   }
  852.   
  853.   frame_on+=dir;
  854.   
  855. }
  856.  
  857. void step_morph::reverse_direction()
  858. {
  859.   step_struct *s=points;
  860.   int i; 
  861.   for (i=0;i<total;i++,s++)
  862.   {
  863.     s->dx=-s->dx;
  864.     s->dy=-s->dy;
  865.     s->dr=-s->dr;
  866.     s->dg=-s->dg;
  867.     s->db=-s->db;    
  868.   }
  869.   dir=-dir;
  870.   
  871. }
  872.  
  873.  
  874. patched_morph::patched_morph(spec_entry *e, bFILE *fp) : jmorph(e,fp)
  875. {
  876.   int i;
  877.   
  878.   patches=fp->read_short();
  879.   pats=(morph_patch *)jmalloc(sizeof(morph_patch)*patches,"patched_morph::points");
  880.   
  881.   for (i=0;i<patches;i++)
  882.   {
  883.     pats[i].patches=fp->read_short();
  884.     if (pats[i].patches)
  885.     {      
  886.       pats[i].patch_data=(unsigned char *)jmalloc(3*pats[i].patches,"patched_morph::patch_data");
  887.       fp->read(pats[i].patch_data,3*pats[i].patches);      
  888.     }
  889.     else
  890.       pats[i].patch_data=NULL;
  891.   }   
  892. }
  893.  
  894.  
  895.